package video

import (
	"common/mildware"
	"common/models"
	"common/validate"
	"errors"
	"github.com/gin-gonic/gin"
	"github.com/go-playground/validator/v10"
	"go.uber.org/zap"
	"strconv"
	"strings"
	"time"
	"video/pkg/dao/redis"
)

const (
	DisLike    = "dis_like"
	Like       = "like"
	Collection = "collection"
)

// SearchLikeByName 模糊查找视频名称
// @Summary 模糊查找视频名称
// @Description 模糊查找视频名称
// @Tags 视频
// @Accept application/json
// @Produce application/json
// @Param object body docModel.DocSearchVideoLikeNameReq false "搜索参数"
// @Security ApiKeyAuth
// @Success 200 {object} docModel.DocResp
// @Router /video/search/name [post]
func (h VHandler) SearchLikeByName(c *gin.Context) {
	resp := new(models.RespData)
	req := new(models.SearchVideoLikeNameReq)
	var res []*models.VideoInfoResp
	if err := c.ShouldBindJSON(req); err != nil {
		errs, ok := err.(validator.ValidationErrors)
		if !ok {
			zap.L().Error("Video:SearchLikeByName with invalid fail", zap.Error(err))
			resp.SendServerBusy(c)
			return
		} else {
			zap.L().Error("Video:SearchLikeByName with invalid fail", zap.Error(errs))
			resp.SendCodeWithMsg(c, models.CodeInvalidParam, validate.RemoveTopStruct(errs.Translate(validate.Trans)))
			return
		}
	}
	//查找数据
	list, total, err := h.M.VideoInfoQueryLikeName(req.VideoName, req.Page, req.Size)
	if err != nil {
		zap.L().Error("Video:h.M.VideoInfoQueryLikeName error", zap.Error(err))
		resp.SendServerBusy(c)
		return
	}
	for _, info := range list {
		demo := &models.VideoInfoResp{
			VideoInfo: info,
			VideoHttp: models.GetHttpUrl(info.VideoId, models.HttpVideo),
		}
		res = append(res, demo)
	}
	resp.Data = res
	resp.Count = total
	resp.SendSuccess(c)
	return
}

// GetRandomVideo 获得分类随机视频
// @Summary 获得分类随机视频
// @Description 获得分类随机视频
// @Tags 视频
// @Accept application/json
// @Produce application/json
// @Param object body docModel.DocGetRandomVideoReq false "搜索参数"
// @Security ApiKeyAuth
// @Success 200 {object} docModel.DocResp
// @Router /video/random/type [post]
func (h VHandler) GetRandomVideo(c *gin.Context) {
	resp := new(models.RespData)
	req := new(models.GetRandomVideoReq)
	var res []*models.VideoInfoResp
	if err := c.ShouldBindJSON(req); err != nil {
		errs, ok := err.(validator.ValidationErrors)
		if !ok {
			zap.L().Error("Video:SearchLikeByName with invalid fail", zap.Error(err))
			resp.SendServerBusy(c)
			return
		} else {
			zap.L().Error("Video:SearchLikeByName with invalid fail", zap.Error(errs))
			resp.SendCodeWithMsg(c, models.CodeInvalidParam, validate.RemoveTopStruct(errs.Translate(validate.Trans)))
			return
		}
	}
	//查找数据
	list, err := h.M.VideoInfoQueryRandom(req.VideType, req.Size, req.OldVideoList)
	if err != nil {
		zap.L().Error("Video:h.M.VideoInfoQueryLikeName error", zap.Error(err))
	}
	if len(list) == 0 {
		resp.SendCode(c, models.CodeNoVideo)
		return
	}
	for _, info := range list {
		demo := &models.VideoInfoResp{
			VideoInfo:         info,
			VideoHttp:         models.GetHttpUrl(info.VideoId, models.HttpVideo),
			UserStatusLike:    false,
			UserStatusCollect: false,
			UserStatusDisLike: false,
		}
		//将地址放到缓存
		//video path:= video_id -> src
		if err = h.R.SetString(redis.VideoPath+info.VideoId, info.Src, 5*time.Minute); err != nil {
			zap.L().Error("Video :h.R.SetString error 1", zap.Error(err))
			resp.SendServerBusy(c)
			return
		}
		//将视频的VideId  - ID
		if err = h.R.SetString(redis.VideIdToID+info.VideoId, strconv.Itoa(int(info.ID)), 5*time.Minute); err != nil {
			zap.L().Error("Video :h.R.SetString error 2 ", zap.Error(err))
			resp.SendServerBusy(c)
			return
		}
		//将视频的点赞缓存 -redis
		str := info.LikePeopleCount + models.SplitFormat + info.DisLikePeopleCount + models.SplitFormat + info.CollectionPeopleCount
		if err = h.R.SetString(redis.VideoInfoLikeOrNo+info.VideoId, str, 5*time.Minute); err != nil {
			zap.L().Error("Video :h.R.SetString error 3", zap.Error(err))
			resp.SendServerBusy(c)
			return
		}
		res = append(res, demo)
	}
	resp.Data = res
	resp.SendSuccess(c)
}

// GetVideoInfoBase 获得视频的信息
// @Summary 获得视频的信息
// @Description 获得视频的信息
// @Tags 视频
// @Accept application/json
// @Produce application/json
// @Param object body docModel.DocGetVideInfoBaseReq false "搜索参数"
// @Security ApiKeyAuth
// @Success 200 {object} docModel.DocResp
// @Router /video/info/one [post]
func (h VHandler) GetVideoInfoBase(c *gin.Context) {
	var (
		videoInfo *models.VideoInfo
		rest      *models.VideoInfoResp
	)

	resp := new(models.RespData)
	req := new(models.GetVideInfoBaseReq)
	if err := c.ShouldBindJSON(req); err != nil {
		errs, ok := err.(validator.ValidationErrors)
		if !ok {
			zap.L().Error("Video:SearchLikeByName with invalid fail", zap.Error(err))
			resp.SendServerBusy(c)
			return
		} else {
			zap.L().Error("Video:SearchLikeByName with invalid fail", zap.Error(errs))
			resp.SendCodeWithMsg(c, models.CodeInvalidParam, validate.RemoveTopStruct(errs.Translate(validate.Trans)))
			return
		}
	}
	videoID, err := h.R.GetString(redis.VideIdToID + req.VideoId)
	if err != nil {
		if errors.Is(err, redis.NoKey) {
			videoInfo, err = h.M.VideoInfoQueryByUid(req.VideoId)
			if err != nil {
				zap.L().Error("Video:videoLikeOrNo h.M.VideoInfoQueryByUid err", zap.Error(err))
				resp.SendServerBusy(c)
				return
			}
		}
	}
	if videoID != "" {
		videoInfo, err = h.M.VideoInfoQueryById(videoID)
		if err != nil {
			zap.L().Error("Video:videoLikeOrNo h.M.VideoInfoQueryById err", zap.Error(err))
			resp.SendServerBusy(c)
			return
		}
	}
	//从redis获得最新的点赞 - 不喜欢 - 收藏
	str, err := h.R.GetString(redis.VideoInfoLikeOrNo + req.VideoId)
	if err != nil {
		zap.L().Error("Video :h.R.SetString error", zap.Error(err))
	}
	if str != "" {
		list := strings.Split(str, models.SplitFormat)
		videoInfo.LikePeopleCount = list[0]
		videoInfo.DisLikePeopleCount = list[1]
		videoInfo.CollectionPeopleCount = list[2]
	}
	rest = &models.VideoInfoResp{
		VideoInfo: videoInfo,
		VideoHttp: models.GetHttpUrl(videoInfo.VideoId, models.HttpVideo),
	}
	resp.Data = rest
	resp.SendSuccess(c)
}

// GetRandomVideoInLike 获得分类随机视频-点赞...
// @Summary 获得分类随机视频-点赞...
// @Description 获得分类随机视频-点赞...
// @Tags 视频
// @Accept application/json
// @Produce application/json
// @Param object body docModel.DocGetRandomVideoReq false "搜索参数"
// @Security ApiKeyAuth
// @Success 200 {object} docModel.DocResp
// @Router /video/random/type/like [post]
func (h VHandler) GetRandomVideoInLike(c *gin.Context) {
	//喜欢
	LikeMap := make(map[string]struct{})
	//不喜欢
	DisLikeMap := make(map[string]struct{})
	//收藏
	CollectionMap := make(map[string]struct{})

	resp := new(models.RespData)
	req := new(models.GetRandomVideoReq)
	var res []*models.VideoInfoResp
	if err := c.ShouldBindJSON(req); err != nil {
		errs, ok := err.(validator.ValidationErrors)
		if !ok {
			zap.L().Error("Video:SearchLikeByName with invalid fail", zap.Error(err))
			resp.SendServerBusy(c)
			return
		} else {
			zap.L().Error("Video:SearchLikeByName with invalid fail", zap.Error(errs))
			resp.SendCodeWithMsg(c, models.CodeInvalidParam, validate.RemoveTopStruct(errs.Translate(validate.Trans)))
			return
		}
	}
	//查看用户的信息
	ID, _, _, err := mildware.GetCyrrentUserID(c)
	if err != nil {
		zap.L().Error("Video:SearchLikeByName mildware.GetCyrrentUserID err", zap.Error(err))
		resp.SendServerBusy(c)
		return
	}
	userInfo, err := h.M.QueryUserInfoByID(ID)
	if err != nil {
		zap.L().Error("Video:SearchLikeByName h.M.QueryUserInfoByID err", zap.Error(err))
		resp.SendServerBusy(c)
		return
	}
	for _, v := range strings.Split(userInfo.LikeVideos, models.SplitFormat) {
		if v == "" {
			LikeMap[v] = struct{}{}
		}
	}
	for _, v := range strings.Split(userInfo.DisLikeVideos, models.SplitFormat) {
		if v == "" {
			DisLikeMap[v] = struct{}{}
		}
	}
	for _, v := range strings.Split(userInfo.CollectionVideos, models.SplitFormat) {
		if v == "" {
			CollectionMap[v] = struct{}{}
		}
	}
	//查找数据
	list, err := h.M.VideoInfoQueryRandom(req.VideType, req.Size, req.OldVideoList)
	if err != nil {
		zap.L().Error("Video:h.M.VideoInfoQueryLikeName error", zap.Error(err))
	}
	if len(list) == 0 {
		resp.SendCode(c, models.CodeNoVideo)
		return
	}
	for _, info := range list {
		demo := &models.VideoInfoResp{
			VideoInfo:         info,
			VideoHttp:         models.GetHttpUrl(info.VideoId, models.HttpVideo),
			UserStatusLike:    false,
			UserStatusCollect: false,
			UserStatusDisLike: false,
		}
		if _, ok := LikeMap[strconv.Itoa(int(info.ID))]; ok {
			demo.UserStatusLike = true
		}
		if _, ok := DisLikeMap[strconv.Itoa(int(info.ID))]; ok {
			demo.UserStatusDisLike = true
		}
		if _, ok := CollectionMap[strconv.Itoa(int(info.ID))]; ok {
			demo.UserStatusCollect = true
		}
		//将地址放到缓存
		//video path:= video_id -> src
		if err = h.R.SetString(redis.VideoPath+info.VideoId, info.Src, 5*time.Minute); err != nil {
			zap.L().Error("Video :h.R.SetString error 1", zap.Error(err))
			resp.SendServerBusy(c)
			return
		}
		//将视频的VideId  - ID
		if err = h.R.SetString(redis.VideIdToID+info.VideoId, strconv.Itoa(int(info.ID)), 5*time.Minute); err != nil {
			zap.L().Error("Video :h.R.SetString error 2 ", zap.Error(err))
			resp.SendServerBusy(c)
			return
		}
		//将视频的点赞缓存 -redis
		str := info.LikePeopleCount + models.SplitFormat + info.DisLikePeopleCount + models.SplitFormat + info.CollectionPeopleCount
		if err = h.R.SetString(redis.VideoInfoLikeOrNo+info.VideoId, str, 5*time.Minute); err != nil {
			zap.L().Error("Video :h.R.SetString error 3", zap.Error(err))
			resp.SendServerBusy(c)
			return
		}
		res = append(res, demo)
	}
	resp.Data = res
	resp.SendSuccess(c)
}

// GetAuthorUpVide 获得用户上传的视频
func (h VHandler) GetAuthorUpVide(c *gin.Context) {
	var res []*models.VideoInfoResp
	resp := new(models.RespData)
	page, size, err := models.GetPageInfo(c)
	if err != nil {
		zap.L().Error("Video :GetAuthorUpVide  models.GetPageInfo error ", zap.Error(err))
		resp.SendCode(c, models.CodeInvalidParam)
		return
	}
	//token 获得ID
	ID, _, _, err := mildware.GetCyrrentUserID(c)
	if err != nil {
		zap.L().Error("Video :GetAuthorUpVide mildware.GetCyrrentUserI error ", zap.Error(err))
		resp.SendServerBusy(c)
		return
	}
	//查对应的视频
	list, total, err := h.M.VideoInfoQueryByAuthor(ID, page, size)
	for _, info := range list {
		demo := &models.VideoInfoResp{
			VideoInfo:         info,
			VideoHttp:         models.GetHttpUrl(info.VideoId, models.HttpVideo),
			UserStatusLike:    false,
			UserStatusCollect: false,
			UserStatusDisLike: false,
		}
		res = append(res, demo)
	}
	resp.Data = res
	resp.Count = total
	resp.SendSuccess(c)
}
